/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package flightlifter;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.Vector;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;

/**
 *
 * @author Matt
 */
public class MeshLoader {

    private Vector tris = new Vector();
    private float bscale = 1.f;
    public Accelerator accelerator;
    public Vector shaders = new Vector();
    public Vector baked = new Vector();
    TextureLoader texLoader = new TextureLoader();
    FloatBuffer verticesFB;
    FloatBuffer uvFB;
    ShortBuffer trianglesFB;
    float[] vertices;
    float[] uvs;
    short[] triangles;
    boolean active = false;
    Texture texture;

    public MeshLoader() {
        accelerator = new ListAccelerator();



    }

    public void draw() {
        if (active) {
            GL20.glUseProgram(0);
            //GL11.glColor3f(1, 1, 1);
            texture.bind();
            GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
            GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);

            GL11.glVertexPointer(3, 0, verticesFB);
            GL11.glTexCoordPointer(2, 0, uvFB);

            GL11.glDrawElements(GL11.GL_TRIANGLES, trianglesFB);
        }
    }

    public void openFile(String path) {

        System.out.println("Loading mesh: " + path);
        //String temp = FlightLifter.readFile(new File(path));


        String temp = Util.readFile(path);
        String[] in = temp.split("\n");

        try {

            //there should be a shader pack with a .mrb extension
            String path2 = path.substring(0, path.length() - 3);
            path2 = path2 + "mrb";

            StringTokenizer ps = new StringTokenizer(path, "/", true);
            String root = "";
            int tokn = ps.countTokens();
            //System.out.println("tokens" + tokn);
            for (int i = 0; i < tokn - 1; i++) {
                root += ps.nextToken();
            }



            //System.out.println("Root:" + root);

            //replace the three letter char
            try {
                String temp2 = Util.readFile(path2);
                String[] in2 = temp2.split("\n");

                //need to load all of the baked textures
                StringTokenizer stk;
                for (int i = 0; i < in2.length; i++) {
                    stk = new StringTokenizer(in2[i], "=[]|,\" ");
                    String tok = stk.nextToken();

                    if (tok.equals("b")) {
                        stk.nextToken();

                        Texture tmp = null;// = new PImage();

                        // tmp = g.loadImage(root + "/" + stk.nextToken());

                        try {
                            tmp = texLoader.getTexture(root + stk.nextToken());

                        } catch (IOException ex) {
                            System.out.println("IOException:" + ex);
                        }

                        baked.add(tmp);

                       // System.out.println("Loaded texture " + tmp);

                    }


                }
            } catch (Exception e) {
                System.out.println("Couldn't find texture file." + e);
            }

            //in.readLine();   //should be muray string descriptor

            StringTokenizer stk;
            boolean foundCamTarget = false;
            for (int j = 1; j < in.length; j++) {
                String[] splt = in[j].split("=");

                //parse shaders
                if (splt[0].equals("shad")) {

                   // System.out.println("parsing shader");

                    stk = new StringTokenizer(splt[1], ",[]");
                    float red = Float.parseFloat(stk.nextToken());
                    float green = Float.parseFloat(stk.nextToken());
                    float blue = Float.parseFloat(stk.nextToken());

                    SolidShader tmp = new SolidShader(red, green, blue);
                    shaders.add(tmp);
                } else if (splt[0].equals("numverts")) {
                    //System.out.println("parsing verts");
                    int numVerts = Integer.parseInt(splt[1]);
                    Vector pts = new Vector();
                    String line;
                    float x, y, z;


                    vertices = new float[3 * numVerts];


                    for (int i = 0; i < numVerts; i++) {
                        j++;
                        line = in[j];
                        stk = new StringTokenizer(line, "=|");
                        stk.nextToken();    //ditch a v
                        x = -bscale * Float.parseFloat(stk.nextToken());
                        z = bscale * Float.parseFloat(stk.nextToken());
                        y = bscale * Float.parseFloat(stk.nextToken());

                        pts.add(new PVector(x, y, z));

                        vertices[3 * i] = x;
                        vertices[3 * i + 1] = y;
                        vertices[3 * i + 2] = z;



                    }
                    verticesFB = FlightLifter.allocFloats(vertices);
                    //verticesFB = BufferUtils.createFloatBuffer(3*numVerts);
                    //verticesFB.put(vertices);
                   // System.out.println("Read:" + pts.size() + "verts");



                    //we've read in the vertices, now read in the corresponding triangles
                    boolean exit = false;
                    float u0, v0, u1, v1, u2, v2;

                    //System.out.println("parsing triangles");
                    ArrayList<Integer> al = new ArrayList();
                    ArrayList<Float> ul = new ArrayList();

                    while (exit == false) {
                        j++;
                        line = in[j];

                        stk = new StringTokenizer(line, "=|");


                        if (stk.nextToken().equals("t")) {

                            int whichVert0 = Integer.parseInt(stk.nextToken());
                            int whichVert1 = Integer.parseInt(stk.nextToken());
                            int whichVert2 = Integer.parseInt(stk.nextToken());
                            int whichShader = Integer.parseInt(stk.nextToken());

                            al.add(new Integer(whichVert0));
                            al.add(new Integer(whichVert1));
                            al.add(new Integer(whichVert2));


                            u0 = Float.parseFloat(stk.nextToken());
                            v0 = Float.parseFloat(stk.nextToken());
                            u1 = Float.parseFloat(stk.nextToken());
                            v1 = Float.parseFloat(stk.nextToken());
                            u2 = Float.parseFloat(stk.nextToken());
                            v2 = Float.parseFloat(stk.nextToken());


                            ul.add(new Float(u0));
                            ul.add(new Float(v0));


                            ul.add(new Float(u1));
                            ul.add(new Float(v1));


                            ul.add(new Float(u2));
                            ul.add(new Float(v2));


                            int whichBake = Integer.parseInt(stk.nextToken());
                            Triangle tmp;


                            if (whichBake == -1) {

                                tmp = new Triangle((Shader) shaders.elementAt(whichShader),
                                        (PVector) pts.elementAt(whichVert0),
                                        (PVector) pts.elementAt(whichVert1),
                                        (PVector) pts.elementAt(whichVert2),
                                        u0, v0, u1, v1, u2, v2, null);

                            } else {
                                this.texture = (Texture) baked.elementAt(whichBake);
                                tmp = new Triangle((Shader) shaders.elementAt(whichShader),
                                        (PVector) pts.elementAt(whichVert0),
                                        (PVector) pts.elementAt(whichVert1),
                                        (PVector) pts.elementAt(whichVert2),
                                        u0, v0, u1, v1, u2, v2, (Texture) baked.elementAt(whichBake));
                            }

                            accelerator.add(tmp);

                        } else {

                            exit = true;
                            //shouldn't have read this line
                            j--;
                        }
                    }
                    int numTris = accelerator.objects.size();

                    System.out.println("Tris:" + numTris);

                    vertices = new float[9 * numTris];
                    triangles = new short[3 * numTris];
                    uvs = new float[6 * numTris];

                    Triangle tmp;
                    for (int i = 0; i < numTris; i++) {
                        tmp = (Triangle) accelerator.objects.elementAt(i);
                        vertices[9 * i] = tmp.vert0.x;
                        vertices[9 * i + 1] = tmp.vert0.y;
                        vertices[9 * i + 2] = tmp.vert0.z;

                        vertices[9 * i + 3] = tmp.vert1.x;
                        vertices[9 * i + 4] = tmp.vert1.y;
                        vertices[9 * i + 5] = tmp.vert1.z;

                        vertices[9 * i + 6] = tmp.vert2.x;
                        vertices[9 * i + 7] = tmp.vert2.y;
                        vertices[9 * i + 8] = tmp.vert2.z;

                    }

                    for (short i = 0; i < al.size(); i++) {
                        //triangles[i] = al.get(i).shortValue();
                        triangles[i] = i;
                    }
                    for (int i = 0; i < ul.size(); i++) {
                        uvs[i] = ul.get(i).floatValue();

                    }

                    verticesFB = FlightLifter.allocFloats(vertices);
                    trianglesFB = FlightLifter.allocShorts(triangles);
                    uvFB = FlightLifter.allocFloats(uvs);

                    System.out.println("UVS capacity:" + uvFB.capacity() + ":" + uvs.length);

                    active = true;
                }
            }
        } catch (Exception e) {
            System.out.println("Error while parsing triangle " + e);
        }
        accelerator.validate();

    }
}


